package org.csu.mypetstore.tools.talkPart;
import org.csu.mypetstore.domain.Sentence;
import org.springframework.stereotype.Component;

import javax.websocket.*;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.CopyOnWriteArraySet;

@ServerEndpoint(value = "/websocket")
@Component
public class WebSocketServlet {
    /**
     * 静态变量，用来记录当前在线连接数。应该把它设计成线程安全的。
     */
    private static int onlineCount = 0;
    /**
     * concurrent包的线程安全Set，用来存放每个客户端对应的CumWebSocket对象。
     */
    private static CopyOnWriteArraySet<WebSocketServlet> webSocketSet = new CopyOnWriteArraySet<WebSocketServlet>();
    /**
     * 与某个客户端的连接会话，需要通过它来给客户端发送数据
     */
    private Session session;
    private static Map<String,String> sessionMap = new HashMap<>();

    /**
     * 连接建立成功调用的方法
     *
     * @param session
     */
    @OnOpen
    public void onOpen(Session session) {
        System.out.println(session.getId());
        this.session = session;
        //加入set中
        webSocketSet.add(this);
        //添加在线人数
        addOnlineCount();
        System.out.println("新连接接入。当前在线人数为：" + getOnlineCount());
    }

    /**
     * 连接关闭调用的方法
     */
    @OnClose
    public void onClose() {
        //从set中删除
        webSocketSet.remove(this);
        //在线数减1
        subOnlineCount();
        System.out.println("有连接关闭。当前在线人数为：" + getOnlineCount());
    }

    /**
     * 收到客户端消息后调用
     *
     * @param message
     * @param session
     */
    @OnMessage
    public void onMessage(String message, Session session) {
        if (sessionMap.containsKey(message) && !sessionMap.get(message).equals(session.getId())) {
            sessionMap.remove(message);
        }
        sessionMap.put(message,session.getId());
        System.out.println("此时sessionMap有"+sessionMap);
    }

    /**
     * 暴露给外部的群发
     *
     * @param sentence
     * @throws IOException
     */
    public static void sendInfo(Sentence sentence) throws IOException {
        sendAll(sentence);
    }

    /**
     * 群发
     *
     * @param sentence
     */
    private static void sendAll(Sentence sentence) {
        if(!sessionMap.containsKey(sentence.getUsername())||!sessionMap.containsKey("bbb")) return;
        if(sentence.getAdmin())
        {
            Arrays.asList(webSocketSet.toArray()).forEach(item -> {
                WebSocketServlet customWebSocket = (WebSocketServlet) item;
                String id = customWebSocket.session.getId();
                if(sessionMap.get(sentence.getUsername()).equals(id))
                {
                    try {
                        customWebSocket.sendMessage(sentence.getUsername());
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            });
        }
        else{
            Arrays.asList(webSocketSet.toArray()).forEach(item -> {
                WebSocketServlet customWebSocket = (WebSocketServlet) item;
                String id = customWebSocket.session.getId();
                if(sessionMap.get("bbb").equals(id))
                {
                    try {
                        customWebSocket.sendMessage(sentence.getUsername());
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            });
        }

    }

    /**
     * 发生错误时调用
     *
     * @param session
     * @param error
     */
    @OnError
    public void onError(Session session, Throwable error) {
        System.out.println("----websocket-------有异常啦");
        error.printStackTrace();
    }

    /**
     * 减少在线人数
     */
    private void subOnlineCount() {
        WebSocketServlet.onlineCount--;
    }

    /**
     * 添加在线人数
     */
    private void addOnlineCount() {
        WebSocketServlet.onlineCount++;
    }

    /**
     * 当前在线人数
     *
     * @return
     */
    public static synchronized int getOnlineCount() {
        return onlineCount;
    }

    /**
     * 发送信息
     *
     * @param message
     * @throws IOException
     */
    public void sendMessage(String message) throws IOException {
        //获取session远程基本连接发送文本消息
        this.session.getBasicRemote().sendText(message);
        //this.session.getAsyncRemote().sendText(message);
    }
}
